package com.addzero.kmp.processor

import cn.hutool.json.JSONUtil
import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.processing.*
import com.google.devtools.ksp.symbol.*
import kotlin.collections.iterator

/**
 * !!注意,图标如果使用了ksp生成,那路由表中引用的图标不会多轮处理
 * 图标扫描器
 * 直接扫描Compose源码中的所有ImageVector图标，生成完整的映射表
 * 同时包含硬编码的常用图标，确保即使无法完全扫描Compose源码也能生成有用的映射
 */
class ImageVectorProcessor(
    private val environment: SymbolProcessorEnvironment
) : SymbolProcessor {

    // 要扫描的图标包列表
    private val iconPackages = listOf(
        "androidx.compose.material.icons.filled",
//        "androidx.compose.material.icons.outlined",
//        "androidx.compose.material.icons.rounded",
//        "androidx.compose.material.icons.sharp",
//        "androidx.compose.material.icons.twotone",
        "androidx.compose.material.icons.automirrored.filled",
        "androidx.compose.material.icons.automirrored.outlined",
//        "androidx.compose.material.icons.automirrored.rounded",
//        "androidx.compose.material.icons.automirrored.sharp",
//        "androidx.compose.material.icons.automirrored.twotone"
    )

    // 图标信息数据类
    data class IconInfo(
        val name: String,
        val qualifiedName: String,
        val type: String
    )

    // 图标类型映射
    private val iconTypeMap = mapOf(
        "Default" to listOf("Icons.Default"),
        "Filled" to listOf("Icons.Filled"),
        "Outlined" to listOf("Icons.Outlined"),
        "Rounded" to listOf("Icons.Rounded"),
        "Sharp" to listOf("Icons.Sharp"),
        "TwoTone" to listOf("Icons.TwoTone"),
        "AutoMirroredFilled" to listOf("Icons.AutoMirrored.Filled"),
        "AutoMirroredOutlined" to listOf("Icons.AutoMirrored.Outlined"),
        "AutoMirroredRounded" to listOf("Icons.AutoMirrored.Rounded"),
        "AutoMirroredSharp" to listOf("Icons.AutoMirrored.Sharp"),
        "AutoMirroredTwoTone" to listOf("Icons.AutoMirrored.TwoTone")
    )

    @OptIn(KspExperimental::class)
    override fun process(resolver: Resolver): List<KSAnnotated> {
        try {
            // 收集所有图标信息
            val allIcons = collectAllIcons(resolver)
            environment.logger.info("收集到 ${allIcons.size} 个图标")

            // 生成图标键文件
            generateIconKeysFile(allIcons)
            
            // 生成优化的图标访问文件（使用when语句）
            generateOptimizedIconMapFile(allIcons)
            
            // 生成图标类型键文件
            generateIconTypeKeysFile()
        } catch (e: Exception) {
            environment.logger.warn("处理图标时出错: ${e.message}")
            e.printStackTrace()
        }

        return emptyList()
    }

    /**
     * 收集所有图标信息
     */
    @OptIn(KspExperimental::class)
    private fun collectAllIcons(resolver: Resolver): List<IconInfo> {
        val icons = mutableListOf<IconInfo>()
        val imageVectorType = resolver.getClassDeclarationByName(
            resolver.getKSNameFromString("androidx.compose.ui.graphics.vector.ImageVector")
        ) ?: return emptyList()

        // 用于跟踪已处理的图标名称，避免重复
        val processedIconNames = mutableSetOf<Pair<String, String>>()
        // 存储被替换的图标映射，格式为：原始图标名称 -> 替换图标信息
        val replacementMap = mutableMapOf<String, Pair<String, String>>()

        // 从各个包中收集图标
        for (packageName in iconPackages) {
            try {
                val declarations = resolver.getDeclarationsFromPackage(packageName)
                val properties = declarations.filterIsInstance<KSPropertyDeclaration>()
                
                properties.filter {
                    // 过滤掉以下划线开头的图标
                    val name = it.simpleName.asString()
                    it.type.resolve().declaration.qualifiedName?.asString() == imageVectorType.qualifiedName?.asString()
                        && !name.startsWith("_")
                }.forEach { property ->
                    val name = property.simpleName.asString()
                    val type = determineIconType(packageName)
                    
                    // 检查属性是否被标记为弃用
                    val isDeprecated = property.annotations.any { annotation ->
                        annotation.shortName.asString() == "Deprecated"
                    }
                    
                    // 如果是弃用的图标，获取替换信息
                    if (isDeprecated) {
                        val deprecatedAnnotation = property.annotations.find { 
                            it.shortName.asString() == "Deprecated" 
                        }
                        
                        deprecatedAnnotation?.arguments?.forEach { arg ->
                            if (arg.name?.asString() == "replaceWith") {
                                val replaceWith = arg.value as? KSAnnotation
                                val expression = replaceWith?.arguments?.find { it.name?.asString() == "expression" }?.value as? String
                                val imports = replaceWith?.arguments?.find { it.name?.asString() == "imports" }?.value as? List<*>
                                
                                if (expression != null && imports != null && imports.isNotEmpty()) {
                                    val firstImport = imports.firstOrNull() as? String
                                    if (firstImport != null) {
                                        // 解析替换表达式，例如 "Icons.AutoMirrored.Filled.KeyboardArrowLeft"
                                        val parts = expression.split(".")
                                        if (parts.size >= 2) {
                                            val replacementIconName = parts.last()
                                            // 确定替换图标的类型
                                            val replacementType = when {
                                                expression.contains("AutoMirrored.Filled") -> "AutoMirroredFilled"
                                                expression.contains("AutoMirrored.Outlined") -> "AutoMirroredOutlined"
                                                expression.contains("Filled") -> "Filled"
                                                expression.contains("Outlined") -> "Outlined"
                                                else -> "Default"
                                            }
                                            
                                            replacementMap[name] = Pair(replacementIconName, replacementType)
                                            environment.logger.info("发现弃用图标: $name, 替换为: $replacementIconName ($replacementType)")
                                        }
                                    }
                                }
                            }
                        }
                        
                        // 如果找到替换信息，跳过当前弃用图标
                        if (replacementMap.containsKey(name)) {
                            return@forEach
                        }
                    }
                    
                    // 检查同一类型下是否已经处理过相同名称的图标
                    val iconKey = Pair(name, type)
                    if (!processedIconNames.contains(iconKey)) {
                        val qualifiedName = "${packageName}.${name}"
                        icons.add(IconInfo(name, qualifiedName, type))
                        processedIconNames.add(iconKey)
                        environment.logger.info("发现图标: $name ($type)")
                    }
                }
            } catch (e: Exception) {
                environment.logger.warn("处理包 $packageName 时出错: ${e.message}")
            }
        }
        
        // 添加替代图标的映射关系到日志
        if (replacementMap.isNotEmpty()) {
            environment.logger.info("发现 ${replacementMap.size} 个弃用图标被替换")
        }

        // 如果没有发现图标，使用硬编码的常见图标列表
        if (icons.isEmpty()) {
            return getHardcodedIconList()
        }

        return icons
    }

    /**
     * 确定图标类型
     */
    private fun determineIconType(packageName: String): String {
        return when {
            packageName.contains("automirrored.filled") -> "AutoMirroredFilled"
            packageName.contains("automirrored.outlined") -> "AutoMirroredOutlined"
            packageName.contains("automirrored.rounded") -> "AutoMirroredRounded"
            packageName.contains("automirrored.sharp") -> "AutoMirroredSharp"
            packageName.contains("automirrored.twotone") -> "AutoMirroredTwoTone"
            packageName.contains("filled") -> "Filled"
            packageName.contains("outlined") -> "Outlined"
            packageName.contains("rounded") -> "Rounded"
            packageName.contains("sharp") -> "Sharp"
            packageName.contains("twotone") -> "TwoTone"
            else -> "Default"
        }
    }

    /**
     * 硬编码的常见图标列表
     */
    private fun getHardcodedIconList(): List<IconInfo> {
        // 基于NodeType.kt中使用的图标和其他常见图标
        val commonIcons = listOf(
            // 文件系统相关图标
            "FolderOpen", "Folder", "InsertDriveFile", "Article", "Image", "AudioFile", "VideoFile", 
            "Code", "PictureAsPdf", "FolderZip",
            
            // 人员与组织相关图标
            "Person", "Business", "Group", "Assignment", "Domain", "AccountTree", "AccountCircle", 
            "People",
            
            // 菜单与导航相关图标
            "Menu", "ViewList", "Navigation", "Link", "SmartButton",
            
            // 数据与报表相关图标
            "Storage", "BarChart", "MenuBook", "TableChart", "FormatListBulleted", "Dashboard",
            
            // 特殊类型图标
            "Star", "Settings", "Notifications", "Warning", "Error", "CheckCircle", "Info",
            
            // 其他常用图标
            "Add", "Delete", "Edit", "Save", "Close", "Search", "Done", "Send", "Share", "Home", 
            "Email", "Phone", "Calendar", "Chat", "ArrowBack", "ArrowForward", "MoreVert", "Refresh"
        )
        
        val iconList = mutableListOf<IconInfo>()
        // 用于跟踪已处理的图标名称，避免重复
        val processedIconNames = mutableSetOf<Pair<String, String>>()
        
        // 为每个图标创建所有可能的类型变体
        for (iconName in commonIcons) {
            // 确保没有下划线开头的图标
            if (iconName.startsWith("_")) continue
            
            for ((typeName, _) in iconTypeMap) {
                // 检查是否已经处理过相同类型下的相同名称图标
                val iconKey = Pair(iconName, typeName)
                if (!processedIconNames.contains(iconKey)) {
                    val qualifiedName = when (typeName) {
                        "Default" -> "androidx.compose.material.icons.Icons.Default.$iconName"
                        "Filled" -> "androidx.compose.material.icons.Icons.Filled.$iconName"
                        "Outlined" -> "androidx.compose.material.icons.Icons.Outlined.$iconName"
                        "Rounded" -> "androidx.compose.material.icons.Icons.Rounded.$iconName"
                        "Sharp" -> "androidx.compose.material.icons.Icons.Sharp.$iconName"
                        "TwoTone" -> "androidx.compose.material.icons.Icons.TwoTone.$iconName"
                        "AutoMirroredFilled" -> "androidx.compose.material.icons.Icons.AutoMirrored.Filled.$iconName"
                        "AutoMirroredOutlined" -> "androidx.compose.material.icons.Icons.AutoMirrored.Outlined.$iconName"
                        "AutoMirroredRounded" -> "androidx.compose.material.icons.Icons.AutoMirrored.Rounded.$iconName"
                        "AutoMirroredSharp" -> "androidx.compose.material.icons.Icons.AutoMirrored.Sharp.$iconName"
                        "AutoMirroredTwoTone" -> "androidx.compose.material.icons.Icons.AutoMirrored.TwoTone.$iconName"
                        else -> continue
                    }
                    
                    iconList.add(IconInfo(iconName, qualifiedName, typeName))
                    processedIconNames.add(iconKey)
                }
            }
        }
        
        return iconList
    }

    /**
     * 生成优化的图标访问文件（使用when语句）
     * 注意: 通过将大的getIcon方法分解成多个子方法，避免单个方法过大
     */
    private fun generateOptimizedIconMapFile(icons: List<IconInfo>) {
        // 按类型分组图标
        val iconsByType = icons.groupBy { it.type }
        
        // 将图标按类型分组，并限制每种类型中的图标数量，避免生成过大的方法
        val maxIconsPerMethod = 100  // 每个子方法中最多包含的图标数量
        
        // 创建方法映射，存储每种类型及对应的方法数量
        val typeMethodsCount = mutableMapOf<String, Int>()
        
        // 创建类型分组，每组包含有限数量的图标
        val typeGroups = mutableMapOf<String, List<List<IconInfo>>>()
        
        // 为每种类型将图标分组
        iconsByType.forEach { (type, icons) ->
            val chunkedIcons = icons.chunked(maxIconsPerMethod)
            typeGroups[type] = chunkedIcons
            typeMethodsCount[type] = chunkedIcons.size
        }
        
        // 使用模板字符串创建文件内容
        val fileContent = """
package com.addzero.kmp.compose.icons

import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.material.icons.rounded.*
import androidx.compose.material.icons.sharp.*
import androidx.compose.material.icons.twotone.*
import androidx.compose.material.icons.automirrored.filled.*
import androidx.compose.material.icons.automirrored.outlined.*
import androidx.compose.material.icons.automirrored.rounded.*
import androidx.compose.material.icons.automirrored.sharp.*
import androidx.compose.material.icons.automirrored.twotone.*

/**
 * 图标数据类，包含图标的键名、类型和实际的ImageVector对象
 */
data class IconData(
    val iconKey: String,
    val iconType: String,
    val vector: ImageVector
)

/**
 * 自动生成的图标访问工具类
 */
object IconMap {
${generateAllIconsSequence(typeGroups)}

${generateGetByTypeMethods()}

${generateGetByNameMethods()}
}
"""
        
        try {
            val dependencies = Dependencies(true)
            environment.codeGenerator.createNewFile(
                dependencies = dependencies,
                packageName = "com.addzero.kmp.compose.icons",
                fileName = "IconMap",
                extensionName = "kt"
            ).use {
                it.write(fileContent.toByteArray())
            }
            environment.logger.info("成功生成IconMap文件")
        } catch (e: Exception) {
            environment.logger.warn("生成IconMap文件失败: ${e.message}")
            e.printStackTrace()
        }
    }

    /**
     * 生成所有图标序列的方法
     */
    private fun generateAllIconsSequence(typeGroups: Map<String, List<List<IconInfo>>>): String {
        val sb = StringBuilder()
        
        // 开始allIcons序列
        sb.append("    /**\n")
        sb.append("     * 所有图标数据的序列\n")
        sb.append("     */\n")
        sb.append("    val allIcons = sequenceOf(\n")
        
        // 每种类型的图标
        var isFirst = true
        typeGroups.forEach { (type, groups) ->
            groups.forEach { iconGroup ->
                iconGroup.forEach { iconInfo ->
                    if (!isFirst) {
                        sb.append(",\n")
                    } else {
                        isFirst = false
                    }
                    sb.append("        IconData(\"${iconInfo.name}\", \"$type\", ${iconTypeMap[type]?.get(0) ?: "Icons.Default"}.${iconInfo.name})")
                }
            }
        }
        
        // 结束allIcons序列
        sb.append("\n    )\n")
        
        return sb.toString()
    }

    /**
     * 生成getByType方法
     */
    private fun generateGetByTypeMethods(): String {
        return """
    /**
     * 获取指定类型的所有图标名称
     * @param type 图标类型
     * @return 该类型下的所有图标名称列表
     */
    fun getByType(type: String): List<String> {
        return allIcons
            .filter { it.iconType == type }
            .map { it.iconKey }
            .toList()
    }

    /**
     * 获取所有图标类型
     * @return 图标类型列表
     */
    fun getAllTypes(): List<String> {
        return allIcons
            .map { it.iconType }
            .distinct()
            .toList()
    }
"""
    }

    /**
     * 生成getByName方法
     */
    private fun generateGetByNameMethods(): String {
        return """
    /**
     * 根据类型和名称获取图标
     * @param type 图标类型
     * @param name 图标名称
     * @return 找到的图标，如果不存在则返回null
     */
    @Composable
    fun getByName(type: String, name: String): ImageVector? {
        return allIcons
            .filter { it.iconType == type && it.iconKey == name }
            .map { it.vector }
            .firstOrNull()
    }

    /**
     * 根据类型和名称获取图标，如果不存在则返回默认图标
     * @param type 图标类型
     * @param name 图标名称
     * @param default 默认图标提供函数
     * @return 找到的图标或默认图标
     */
    @Composable
    fun getByNameOrDefault(type: String, name: String, default: @Composable () -> ImageVector): ImageVector {
        return getByName(type, name) ?: default()
    }
    
    /**
     * 通过图标名称获取图标数据
     * @param iconKey 图标名称
     * @return 图标数据对象IconData
     */
    @Composable
    operator fun get(iconKey: String): IconData {
        return allIcons
            .filter { it.iconKey == iconKey }
            .firstOrNull() 
            ?: allIcons
                .filter { it.iconType == "Filled" }
                .firstOrNull()
                ?: IconData("Info", "Filled", Icons.Filled.Info)
    }
"""
    }

    /**
     * 生成图标键文件
     */
    private fun generateIconKeysFile(icons: List<IconInfo>) {
        // 按图标名称的大写形式分组，以确保名称唯一性（大小写不敏感）
        val uniqueIconNames = mutableMapOf<String, String>()
        
        // 优先保留图标名称，处理可能的重复情况
        icons.forEach { icon ->
            val upperCaseName = icon.name.uppercase()
            if (!uniqueIconNames.containsKey(upperCaseName)) {
                uniqueIconNames[upperCaseName] = icon.name
            }
        }
        
        // 收集所有不重复的图标名称
        val iconNames = uniqueIconNames.values.sorted()
        
        // 使用模板字符串生成文件内容
        val fileContent = """
package com.addzero.kmp.compose.icons

/**
 * 自动生成的图标键常量
 */
object IconKeys {
    // 图标名称常量
${iconNames.joinToString("\n") { "    const val ${it.uppercase()} = \"$it\"" }}
    
    // 图标类型常量
${iconTypeMap.keys.joinToString("\n") { "    const val TYPE_${it.uppercase()} = \"$it\"" }}
}
"""
        
        try {
            environment.codeGenerator.createNewFile(
                dependencies = Dependencies(true),
                packageName = "com.addzero.kmp.compose.icons",
                fileName = "IconKeys",
                extensionName = "kt"
            ).use {
                it.write(fileContent.toByteArray())
            }
            environment.logger.info("成功生成IconKeys文件")
        } catch (e: Exception) {
            environment.logger.warn("生成IconKeys文件失败: ${e.message}")
            e.printStackTrace()
        }
    }

    /**
     * 生成图标类型键文件，用于IDE自动提示
     */
    private fun generateIconTypeKeysFile() {
        val fileContent = """
package com.addzero.kmp.compose.icons

/**
 * 图标类型常量类
 * 为IDE提供自动完成提示支持
 */
object IconTypeKeys {
${iconTypeMap.keys.joinToString("\n") { 
    """    /**
     * ${getTypeDescription(it)}
     */
    const val ${it.uppercase()} = "$it" """ 
}}
}
"""
        
        try {
            environment.codeGenerator.createNewFile(
                dependencies = Dependencies(true),
                packageName = "com.addzero.kmp.compose.icons",
                fileName = "IconTypeKeys",
                extensionName = "kt"
            ).use {
                it.write(fileContent.toByteArray())
            }
            environment.logger.info("成功生成IconTypeKeys文件")
        } catch (e: Exception) {
            environment.logger.warn("生成IconTypeKeys文件失败: ${e.message}")
            e.printStackTrace()
        }
    }
    
    /**
     * 获取图标类型的描述
     */
    private fun getTypeDescription(type: String): String {
        return when (type) {
            "Default" -> "默认图标类型"
            "Filled" -> "填充图标类型"
            "Outlined" -> "轮廓图标类型"
            "Rounded" -> "圆角图标类型"
            "Sharp" -> "尖角图标类型"
            "TwoTone" -> "双色调图标类型"
            "AutoMirroredFilled" -> "自动镜像填充图标类型"
            "AutoMirroredOutlined" -> "自动镜像轮廓图标类型" 
            "AutoMirroredRounded" -> "自动镜像圆角图标类型"
            "AutoMirroredSharp" -> "自动镜像尖角图标类型"
            "AutoMirroredTwoTone" -> "自动镜像双色调图标类型"
            else -> "未知图标类型"
        }
    }

    /**
     * 处理器提供者
     */
    class ImageVectorProvider : SymbolProcessorProvider {
        override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
            return ImageVectorProcessor(environment)
        }
    }
}

object JsonUtil {
    fun toJson(obj: Any): String? {
        return try {
            JSONUtil.toJsonStr(obj)
        } catch (e: Exception) {
            "{\"error\":\"序列化失败: ${e.message}\"}"
        }
    }
}